#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__
#include "../mqcommon/logger.hpp"
#include "../mqcommon/helper.hpp"
#include "../mqcommon/mq_msg.pb.h"
#include <iostream>
#include <vector>
#include <string>

class Router{
public:
    static bool isLegalRoutingKey(const std::string &routing_key){
        //routingkey秩序判断是否包含有非法字符即可，合法字符（a~z, A~Z, 0~9, ., _）
        for (auto &ch : routing_key){
            if ((ch >= 'a' && ch <= 'z') ||
                (ch >= 'A' && ch <= 'Z') ||
                (ch >= '0' && ch <= '9') ||
                (ch == '_' || ch == '.')){
                    continue;
                }
            return false;
        }
        return true;
    }

    static bool isLegalBindingKey(const std::string &binding_key){
        //1. 判断是否包含有非法字符，合法字符（a~z, A~Z, 0~9, ., _, *, #）
        for (auto &ch : binding_key){
            if ((ch >= 'a' && ch <= 'z') ||
                (ch >= 'A' && ch <= 'Z') ||
                (ch >= '0' && ch <= '9') ||
                (ch == '_' || ch == '.') ||
                (ch == '*' || ch == '#')){
                    continue;
                }
            return false;
        }
        //2. *和#必须独立存在：news.music.*     news.music.#
        std::vector<std::string> sub_words;
        StrHelper::split(binding_key, ".", sub_words);
        for (auto &word : sub_words){
            if (word.size() > 1 && 
                word.find("*") != std::string::npos &&
                word.find("#") != std::string::npos){
                return false;
            }
        }
        //3. *和#不能连续出现即#两边不能有*或#,因为#包含了*的情况。#匹配0个或多个单词，*匹配1个单词
        for (int i = 1; i < sub_words.size(); i++){
            if (sub_words[i] == "#" && sub_words[i-1] == "*"){
                return false;
            }
            if (sub_words[i] == "#" && sub_words[i-1] == "#"){
                return false;
            }
            if (sub_words[i] == "*" && sub_words[i-1] == "#"){
                return false;
            }
        }
    
    return true; 
    }

    static bool route(mymq::ExchangeType type, const std::string &routing_key, const std::string &binding_key){
        if (type == mymq::ExchangeType::DIRECT){
            return (routing_key == binding_key);
        }else if (type == mymq::ExchangeType::FANOUT){
            return true;
        }
        //主题交换：要进行模式匹配。 news.#  & news.music.pop
        //1. 将binding_key与routing_ley进行字符串分割，得到各个单词数组
        std::vector<std::string> bkeys, rkeys;
        int n_bkey = StrHelper::split(binding_key, ".", bkeys);
        int n_rkey = StrHelper::split(routing_key, ".", rkeys);
        //2. 定义标记数组，并初始化[0][0]位置为true，其他位置为false
        std::vector<std::vector<bool>> dp(n_bkey + 1, std::vector<bool>(n_rkey + 1, false));
        dp[0][0] = true;
        //3. 如果binding_key以#起始，则将#对应行的第0列置为1
        if (bkeys[0] == "#"){
            dp[1][0] = true;
        }
        //4. 使用routing_key中的每个单词与binding_key中的每个单词进行匹配并标记数组
        for (int i = 1; i <= n_bkey; i++){
            for (int j = 1; j<=n_rkey; j++){
                //如果当前bkey是*，或者两个单词相同，则表示单词匹配成功，从左上方继承结果
                if (bkeys[i - 1] == "*" || bkeys[i - 1] == rkeys[j - 1]){
                    dp[i][j] = dp[i-1][j-1];
                }else if (bkeys[i - 1] == "#"){
                    //如果当前bkey是#，则需要从左上、左边、上边继承结果
                    dp[i][j] = dp[i-1][j-1] | dp[i][j-1] | dp[i-1][j];
                }
            }
        }
        return dp[n_bkey][n_rkey];
    }
};

#endif